package edu.siu.math.egut.local;

import java.io.Serializable;
import java.util.regex.Pattern;

import edu.siu.math.egut.main.OutputStyle;
import edu.siu.math.egut.util.BadSubstitutionException;
import edu.siu.math.egut.util.Polynomial;
import edu.siu.math.egut.util.PolynomialReadException;

/**
 * @author josephhundley
 *
 */
public class Inequality implements Serializable{
    
    /**
     * 
     */
    private static final long serialVersionUID = 471577674623784673L;
    public static final Pattern INEQUALITY = Pattern.compile(".*(>|<|(>=)|(<=)).*");
    public static final Pattern SYMBOL = Pattern.compile(">|<|(>=)|(<=)");
   

    public enum Symbol {
	GREATERTHAN, GREATERTHANOREQUALTO
    }
    
    private Polynomial leftHandSide;
    private Symbol symbol;
    private Polynomial rightHandSide;
    public static Inequality read(String s) throws InequalityReadException, PolynomialReadException {
	if(!INEQUALITY.matcher(s).matches())
	    throw new InequalityReadException();
	String[] sides = s.split("(<=)|(>=)|(=<)|(=>)|<|>");
	if( sides.length > 2)
	    throw new InequalityReadException();
	String symbol = s.substring(sides[0].length(), s.length()-sides[1].length());
	if(!SYMBOL.matcher(symbol).matches())
	    throw new InequalityReadException();

	Polynomial p = Polynomial.read(sides[0]);
	Polynomial q = Polynomial.read(sides[1]);

	if( symbol.matches("(<=)|(=<)"))
		return new Inequality(q, Symbol.GREATERTHANOREQUALTO, p);
	if( symbol.matches("<"))
	    return new Inequality(q, Symbol.GREATERTHAN, p);
	if( symbol.matches("(>=)|(=>)"))
		return new Inequality(p, Symbol.GREATERTHANOREQUALTO, q);
	if( symbol.matches(">"))
	    return new Inequality(p, Symbol.GREATERTHAN, q);
	
	throw new InequalityReadException();


    
    }
    public Inequality(Polynomial leftHandSide, Symbol symbol,
	    Polynomial rightHandSide) {
	super();
	this.leftHandSide = leftHandSide;
	this.symbol = symbol;
	this.rightHandSide = rightHandSide;
    }
    
    public String toString(){
	return toString(OutputStyle.SCREEN);
    }
    public String toString(OutputStyle sty) {
	switch ( sty )
	{
	case SCREEN:
	    return leftHandSide.toString() + ((symbol == Symbol.GREATERTHAN)?" > ":" >= ") + rightHandSide.toString();
	case TEX:
	    StringBuilder sb = new StringBuilder();
	    if( leftHandSide == Polynomial.create(1) || leftHandSide == Polynomial.create(-1))
		sb.append("1");
	    else
	     sb.append("|"+leftHandSide.toString(sty) +"|");
	    
	    sb.append( (symbol == Symbol.GREATERTHAN)?" > ":" \\ge " );
	    if( rightHandSide == Polynomial.create(1) || rightHandSide == Polynomial.create(-1))
		sb.append("0");
	    else
		sb.append( "|"+rightHandSide.toString(sty) +"|");
	     return sb.toString();
	}
	return this.toString();
    
    }
    public Inequality update() {
	Polynomial newLHS = Polynomial.update(leftHandSide);
	Polynomial newRHS = Polynomial.update(rightHandSide);
	return new Inequality(newLHS, symbol, newRHS);
    }
    public Polynomial getLHS() {
	return this.leftHandSide;
    }
    public Polynomial getRHS() {
	return this.rightHandSide;
    }
    public void replace(String s1, Polynomial p1) throws BadSubstitutionException {
	leftHandSide = leftHandSide.replace(s1,p1);
	rightHandSide = rightHandSide.replace(s1,p1);
	
    }
    public void replace(String s1, String s2) {
	leftHandSide = leftHandSide.old_replace(s1,s2);
	rightHandSide = rightHandSide.old_replace(s1,s2);
	
    }
    public boolean matches(Inequality i) {
	return i.leftHandSide == leftHandSide && i.symbol == symbol && i.rightHandSide == rightHandSide;
    }
    public boolean implies(Inequality i) {
	if(symbol == Symbol.GREATERTHAN)
	    return i.leftHandSide == leftHandSide && i.rightHandSide == rightHandSide;
	return matches(i);
    }
    public Symbol getSymbol() {
	return symbol;
    }
    public boolean involves(String x) {
	
	return (this.leftHandSide.dependsOn(x)||rightHandSide.dependsOn(x));
    }
    public boolean matches(Polynomial p, Symbol sym, Polynomial q) {
	return getLHS() == p && getSymbol() == sym && getRHS()== q;
    }
	   public boolean matches(int i, Symbol sym, Polynomial q) {
		return matches(Polynomial.create(i), sym, q);
	    }
	   public boolean matches(int i, Symbol sym, String x) {
		return matches(Polynomial.create(i), sym, Polynomial.create(x));
	    }
 
    
}
